package com.cs.redis.configurer;


import java.time.Duration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;

import com.cs.redis.utils.RedisPropertyUtil;
import com.cs.redis.utils.RedisUtil;

@Configuration
@EnableConfigurationProperties
public class MyBeanDefinitionRegistryRedis implements BeanDefinitionRegistryPostProcessor {

	private static final Logger logger = LoggerFactory.getLogger(MyBeanDefinitionRegistryRedis.class);

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		logger.info("Invoke Metho MyBeanDefinitionRegistryRedis postProcessBeanDefinitionRegistry");
		
		RedisPropertyUtil redisPropertyUtil = new RedisPropertyUtil("application.properties");
        
        String nameList = redisPropertyUtil.getProperty("csboot.redis.name");
        if(!StringUtils.isEmpty(nameList))
    	{
        	String[] namesplit = nameList.split(",");
            for(String name : namesplit)
            {
            	if(StringUtils.isEmpty(name))
            	{
            		continue;
            	}
            	registerBean(registry, name);
            }
    		
    	}
	}
	
	 private void registerBean(BeanDefinitionRegistry registry, String name){
		 RedisPropertyUtil mybaitsPropertyUtil2 = new RedisPropertyUtil(name+".properties");
		 String redisNname = mybaitsPropertyUtil2.getProperty("redis.name");
		 String hostname = mybaitsPropertyUtil2.getProperty("redis."+redisNname+".hostName");
		 String portstr = mybaitsPropertyUtil2.getProperty("redis."+redisNname+".port");
		 String databasestr = mybaitsPropertyUtil2.getProperty("redis."+redisNname+".database");
		 String password = mybaitsPropertyUtil2.getProperty("redis."+redisNname+".password");
		 String timeoutstr = mybaitsPropertyUtil2.getProperty("redis."+redisNname+".timeout");
		 
		 int port = Integer.valueOf(portstr.trim());
		 int database = Integer.valueOf(databasestr.trim());
		 int timeout = Integer.valueOf(timeoutstr.trim());
		 
		 BeanDefinitionBuilder builderJedisConnectionFactory = BeanDefinitionBuilder.genericBeanDefinition(JedisConnectionFactory.class);
		 RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
	        redisStandaloneConfiguration.setHostName(hostname);
	        redisStandaloneConfiguration.setPort(port);
	        redisStandaloneConfiguration.setDatabase(database);
	        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));

	        JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
	        jedisClientConfiguration.connectTimeout(Duration.ofMillis(timeout));//  connection timeout
		 builderJedisConnectionFactory.addConstructorArgValue(redisStandaloneConfiguration);
		 builderJedisConnectionFactory.addConstructorArgValue(jedisClientConfiguration.build());
		 //builder.addPropertyValue(name, value);
		 //builder.addConstructorArgValue(value);
	        registry.registerBeanDefinition(redisNname+"factory", builderJedisConnectionFactory.getBeanDefinition());
	        
	        BeanDefinitionBuilder builderRedisTemplate = BeanDefinitionBuilder.genericBeanDefinition(RedisTemplate.class);
	        builderRedisTemplate.addPropertyValue("keySerializer", new StringRedisSerializer());
	        builderRedisTemplate.addPropertyValue("hashKeySerializer", new StringRedisSerializer());
	        builderRedisTemplate.addPropertyValue("hashValueSerializer", new GenericJackson2JsonRedisSerializer());
	        builderRedisTemplate.addPropertyValue("valueSerializer", new GenericJackson2JsonRedisSerializer());
	        builderRedisTemplate.addPropertyValue("enableTransactionSupport", true);
	        builderRedisTemplate.addPropertyValue("keySerializer", new StringRedisSerializer());
	        builderRedisTemplate.addPropertyReference("connectionFactory", redisNname+"factory");
	        registry.registerBeanDefinition(redisNname+"RedisTemplate", builderRedisTemplate.getBeanDefinition());
	        
	        BeanDefinitionBuilder builderRedisUtil = BeanDefinitionBuilder.genericBeanDefinition(RedisUtil.class);
	        builderRedisUtil.addPropertyReference("redisTemplate", redisNname+"RedisTemplate");
	        registry.registerBeanDefinition(redisNname+"Util", builderRedisUtil.getBeanDefinition());
	    }
}
